/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.ac.iie.agent.service;

import cn.ac.iie.agent.tools.FileTools;
import cn.ac.iie.agent.tools.FtpTools;
import cn.ac.iie.agent.tools.PropsFiles;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.log4j.Logger;

/**
 *
 * @author dell
 */
public class FtpDownloadDataFilesThread implements Runnable {

    private static Logger logger = Logger.getLogger(FtpDownloadDataFilesThread.class);

    private String subjobid;
    private String jsonFileName;
    private String ftpIP;
    private int ftpPort;
    private String username;
    private String password;
    private String localPath;
    private String filePath;
    private String namespace;
    private String ftpErrorPath;
    private String src;
    private FtpDownloadJsonFilesThread ftpDownloadJsonFilesThread;

    public FtpDownloadDataFilesThread(String subjobid, String jsonFileName, String ftpIP, int ftpPort, String username, String password, String localPath, String filePath, String namespace, String ftpErrorPath, FtpDownloadJsonFilesThread ftpDownloadJsonFilesThread) {
        this.subjobid = subjobid;
        this.jsonFileName = jsonFileName;
        this.ftpIP = ftpIP;
        this.ftpPort = ftpPort;
        this.username = username;
        this.password = password;
        this.localPath = localPath;
        this.filePath = filePath;
        this.namespace = namespace;
        this.ftpErrorPath = ftpErrorPath;
        this.ftpDownloadJsonFilesThread = ftpDownloadJsonFilesThread;
    }

    @Override
    public void run() {
        FtpTools ftpTools = new FtpTools();
        PropsFiles ps = new PropsFiles();
        String ftpPathPrefix = ps.getValue("uploadType");
        FileTools fileTools = new FileTools();
        //解析JSON文件,获取数据文件名
        List<String[]> errMsglist = new ArrayList<String[]>();
        logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " start to analyze the JSON file: " + localPath + "Ctrl/" + jsonFileName);
        List<Map<String, String>> dataFileList = new ArrayList<Map<String, String>>();
        boolean analyzeFlag = false;
        try {
            dataFileList = parseJson(localPath + "Ctrl/" + jsonFileName, "file_list");
            if (dataFileList == null || dataFileList.isEmpty()) {
                logger.debug(subjobid + " " + jsonFileName + " ip: " + ftpIP + " dataFileList is empty");
                //错误信息添加进errMsglist
                String[] message = {jsonFileName, "2"};
                errMsglist.add(message);
                fileTools.deleteFile(localPath + "Ctrl/" + jsonFileName);
            } else {
                logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " analyzFlag = true");
                analyzeFlag = true;
            }
        } catch (Exception e) {
            logger.error(subjobid + " " + jsonFileName + " ip: " + ftpIP + " analyze the JSON file:" + localPath + "Ctrl/" + jsonFileName + " failed!cause: " + e.getMessage(), e);
            String[] message = {jsonFileName, "2"};
            errMsglist.add(message);
            //删除本地json文件
            fileTools.deleteFile(localPath + "Ctrl/" + jsonFileName);
        }

        //下载数据文件
        String returnFlag = "";
        logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " download!");
        //创建ftp连接
        FTPClient createFtpClient = ftpTools.createFtpClient(ftpIP, ftpPort, username, password);
        if (analyzeFlag) {
            String filename = "";
            for (int i = 0; i < dataFileList.size(); i++) {
                Map<String, String> str = dataFileList.get(i);
                String downFile = "";
                filename = str.get("name");
                try {
                    if (createFtpClient == null) {
                        createFtpClient = ftpTools.createFtpClient(ftpIP, ftpPort, username, password);
                    }
                    String date = filename.substring(1, filename.lastIndexOf("/"));
                    String realName = filename.substring(filename.lastIndexOf("/") + 1, filename.length());
                    logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " download the data file, and the data file is: " + filename + " from ftpPath: " + filePath + "Data/" + date + " to localPath: " + localPath + "Data/" + date);
                    downFile = ftpTools.downDataFile(createFtpClient, ftpIP, filePath + "Data/" + date, localPath + "Data/" + date, realName);
                    logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " download file " + downFile);
                    if (downFile.equals("ERROR")) {
                        logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " DataTimeout, ReConnect!");
                        ftpTools.destroyFtpClient(createFtpClient);
                        createFtpClient = ftpTools.createFtpClient(ftpIP, ftpPort, username, password);
                        logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " download, ReTry!");
                        String dd = ftpTools.downDataFile(createFtpClient, ftpIP, filePath + "Data/" + date, localPath + "Data/" + date, realName);
                        logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " download file " + dd);
                        if (dd.equals("ERROR")) {
                            ftpTools.destroyFtpClient(createFtpClient);
                            createFtpClient = ftpTools.createFtpClient(ftpIP, ftpPort, username, password);
                        }
                    }
                } catch (Exception e) {
                    logger.error(subjobid + " " + jsonFileName + e.getMessage(), e);
                } finally {
                    if (!downFile.equals("true")) {
                        String[] message = {filename, "1"};
                        errMsglist.add(message);
                    }
                    returnFlag = returnFlag + downFile + ",";
                }
            }
            //关闭ftp连接
            if (createFtpClient != null) {
                ftpTools.destroyFtpClient(createFtpClient);
            }
        }

        if (returnFlag.contains("false") || !analyzeFlag || returnFlag.contains("ERROR")) {
            logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " return flag" + returnFlag);
            String str = "";
            String errMsg = "\"src\":\"" + src + "\",\"file_list\":[";
            if (!errMsglist.isEmpty()) {
                for (int j = 0; j < errMsglist.size(); j++) {
                    str = str + "{\"name\":\"" + errMsglist.get(j)[0] + "\",\"code\":\"" + errMsglist.get(j)[1] + "\"}" + ",";
                }
                errMsg = "{" + errMsg + str.substring(0, str.length() - 1) + "]}";
                logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " write error JSON file: Err_" + jsonFileName + ", and message is: " + errMsg);
                fileTools.mkFile(localPath + "Ctrl/" + "/Err_" + jsonFileName, errMsg);

                //上传至服务器ERROR路径下
                logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " begin to upload error JSON file: Err_" + jsonFileName + ",the localPath is: " + localPath + "Ctrl/" + " ,the errorPath is: " + ftpErrorPath);
                boolean upload = ftpTools.upload(ftpIP, ftpPort, username, password, localPath + "Ctrl/Err_" + jsonFileName, ftpPathPrefix, ftpErrorPath, "Err_" + jsonFileName);
                logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " upload error JSON file return " + upload);
                //.ok文件上传至服务器
                boolean okFile = ftpTools.okFile(ftpIP, ftpPort, username, password, ftpPathPrefix + ftpErrorPath, "Err_" + jsonFileName);
                logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " upload error JSON.ok file return " + okFile);

                //本地删除ErrorJson文件
                logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " delete error JSON file, the name is: " + "/Err_" + jsonFileName);
                fileTools.deleteFile(localPath + "Ctrl/" + "/Err_" + jsonFileName);
                logger.info(subjobid + " " + jsonFileName + " " + localPath + "Ctrl/" + jsonFileName + "执行失败，删除对应Ctrl目录下的文件。");
                //删除本地Ctrl，Data下文件
                fileTools.deleteFile(localPath + "Ctrl/" + jsonFileName);
                for (int i = 0; i < dataFileList.size(); i++) {
                    logger.info(subjobid + " " + jsonFileName + "dataFileList.size()=" + dataFileList.size());
                    String filename = dataFileList.get(i).get("name");
                    logger.info(subjobid + " " + jsonFileName + " 删除Data目录下" + localPath + "Data" + filename);
                    fileTools.deleteFile(localPath + "Data" + filename);
                }

                if (upload) {
                    //Ctrl目录下JSON文件生成dwd,上传至服务器
                    logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " upload dwd JSON file, the name is: " + filePath + "Ctrl/" + jsonFileName);
                    boolean dwdFile = ftpTools.dwdFile(ftpIP, ftpPort, username, password, filePath + "Ctrl", jsonFileName, namespace);
                    logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " upload dwd JSON file return " + dwdFile);
                }
            }
        } else if (!returnFlag.contains("false") && analyzeFlag) {
            ftpDownloadJsonFilesThread.plusSucessUploadFileNumber();
            //该Ctrl下的json执行完，对应Ctrl生成.ok文件
            fileTools.mkFile(localPath + "Ctrl/" + jsonFileName + ".ok", "ok");
            //Ctrl目录下JSON文件生成dwd,上传至服务器
            logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " upload dwd JSON file, the name is: " + filePath + "Ctrl/" + jsonFileName);
            boolean dwdFile = ftpTools.dwdFile(ftpIP, ftpPort, username, password, filePath + "Ctrl", jsonFileName, namespace);
            logger.info(subjobid + " " + jsonFileName + " ip: " + ftpIP + " upload dwd JSON file return " + dwdFile);
        }
    }

    public List<Map<String, String>> parseJson(String jsonFile, String nameNode) {
        File file = new File(jsonFile);
        if (file.exists() && file.isFile()) {
            InputStream is = null;
            String jsonString = null;
            try {
                is = new BufferedInputStream(new FileInputStream(file));
                long contentLength = file.length();
                ByteArrayOutputStream outstream = new ByteArrayOutputStream(contentLength > 0 ? (int) contentLength : 1024);
                byte[] buffer = new byte[4096];
                int len;
                while ((len = is.read(buffer)) > 0) {
                    outstream.write(buffer, 0, len);
                }
                outstream.flush();
                outstream.close();
                jsonString = new String(outstream.toByteArray(), "utf-8");
            } catch (FileNotFoundException ex) {
                logger.error(jsonFile + " " + ex.getMessage(), ex);
            } catch (IOException ex) {
                logger.error(jsonFile + " " + ex.getMessage(), ex);
            } catch (Exception ex) {
                logger.error(jsonFile + " " + ex.getMessage(), ex);
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (Exception e) {
                    }
                }
            }
            //parseJsonString
            JSONObject jsonObject = JSONObject.fromObject(jsonString);
            src = jsonObject.get("src").toString();
            logger.info(jsonFile + " " + "the JSON file " + jsonFile + " src: " + src);
            JSONArray jsonArray = jsonObject.getJSONArray(nameNode);
            List<Map<String, String>> rsList = new ArrayList<Map<String, String>>();
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject object = (JSONObject) jsonArray.get(i);
                Map<String, String> map = new HashMap<String, String>();
                for (Iterator<?> iter = object.keys(); iter.hasNext();) {
                    String key = (String) iter.next();
                    String value = object.get(key).toString();
                    map.put(key, value);
                    break;
                }
                rsList.add(map);
            }
            return rsList;
        } else {
            return null;
        }
    }
}
